這是一個表單,廢話。
我們先前設計了一個簡單的登入功能,但這些欄位都還沒有作用,今天我們來實作,如何從表單拿到使用者輸入的值,並且在以後接上API,送到後端伺服器。
<form>
帳號 <input type="text"><br>
密碼 <input type="password"><br>
<input type="submit" value="Login" (click)="loginAction()">
</form>
這是原先的程式碼,我現在想要在 ts
看到這些欄位的值,我可以使用 Two-way Binding,那我們必須先宣告一組變數,然後跟 ngModel
binding:
// login.component.ts
login = {
username: '',
pwd : ''
};
// login.component.html
<form
帳號 <input type="text" [(ngModel)]="login.username"><br>
密碼 <input type="password" [(ngModel)]="login.pwd"><br>
<input type="submit" value="Login" (click)="loginAction()">
</form>
儲存之後會看到 F12 有錯誤訊息,它說,如果我們在 <form>
裡面用了 ngModel
,那該元素就要設定 name
這個欄位。OK,我們把 name
加上。
那在設定了 name
之後,就等於給 Angular 一個識別的名牌,這時我們可以在 <form>
加上範本參考變數,並指定為 ngForm,我這邊的變數名稱是 #f
。
<form #f="ngForm">
這個範本參考變數,可以當作是一個屬性來用,以井字號#開頭,後面接妳的變數名字 f、f123、aaaaa ...等都可以,做這樣的宣告之後,我們就可以在這份 html 裡,用這個變數名稱來存取DOM。
所以我們可以在下方,用這樣的方式來看表單內容:
{{f.value| json}}
f 是我們剛剛的 <form>
物件,然後取它的 value ,用前面學到的 Pipe 解析成 json 格式。
就可以看到表單目前的值:
不使用 pipe 的話,只會印出:
[object Object]
也可以試著比較,在範本參考變數後面指定 ngForm
,印出來的內容有甚麼差別,下面的 #A
就是沒有指定 ngForm
的變數:
// login.component.html
<form #f="ngForm" #A> ...</form>
{{f| json}}
<br>
<br>
{{A| json}}
字很小,但可以看的出來印出的結果不同。所以指定 ngForm
,就會將變數解析成 Angular 自己的表單物件:
// login.component.html
{{f}}
<br>
<br>
{{A}}
可以看出是兩種不同的 DOM 物件:
有了雙向綁定,我就可以在我按下 Login 按鈕時,抓我現在的變數值。
loginAction() {
this.loginRequest.emit(true);
console.log(this.login);
}
或是我們把範本參考變數的值傳進 function,我在 function 新增一個 $event
來接:
// login.component.ts
loginAction($event) {
this.loginRequest.emit(true);
console.log($event.value);
}
然後在 (click)="loginAction()
的地方傳入 f
,就是我們的 form 的變數。
<form #f="ngForm">
...
<input type="submit" value="Login" (click)="loginAction(f)">
</form>
可以印出一樣的東西:
習慣上我們會把 submit
的動作寫在 form
的屬性,所以我們把 loginAction()
移到 <form>
中跟 ngSubmit
做 Event Binding。此時再把 <input type="submit">
的(click)
綁定拿掉。因為按下 Login
按鈕時,就會觸發 ngSubmit
了。
// login.component.html
<form #f="ngForm" (ngSubmit)="loginAction(f)" >
<input type="submit" value="Login">
</form>
且在 Submit 表單時,如果沒有執行 onSubmit()
,貌似會跳出這個警告,(Angular 應該是認 onSubmit() 這個名字):
表單的功能不只這樣,你還可以透過 ngForm 屬性來取得表單的一些狀態,比方被點選過、未點選過、輸入過文字...等等,這些屬性同樣適用於 ngModel,也就是表單內每個標籤上都可以使用,只要在範本參考變數後面指派 ngModel
就可以了,像這樣:
#name="ngModel"
// login.component.html
<form #f="ngForm >
帳號 <input type="text" [(ngModel)]="login.username" name="username"
#name="ngModel"><br>
...
</form>
Form touched : {{f.touched}}<br>
Form untouched : {{f.untouched}}<br>
Form dirty : {{f.dirty}}<br>
Name touched : {{name.dirty}}<br>